#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Copyright (c) 61DUke.

# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
# PURPOSE.
# See the Readme Document for more details.
# Create: 2020-12-27

from PIL import Image, ImageDraw, ImageFont

__all__ = ["addition_icon_autograph"]


def _circle(icon_image, reset_icon_image, icon_size):
    """
    Circle Base Function

    :param icon_image:
    :param reset_icon_image:
    :param icon_size:
    :return: circle icon image object

    """
    p_image = icon_image.load()  # Access object of pixel
    preset_icon_image = reset_icon_image.load()
    r = float(icon_size / 2)  # Abscissa of center of circle
    r3 = int(icon_size // 2)
    for i in range(icon_size):
        for j in range(icon_size):
            lx = abs(i - r)  # to center of circle
            ly = abs(j - r)  # the ordinate of the distance from the center of the circle
            l = (pow(lx, 2) + pow(ly, 2)) ** 0.5  # trigonometric radius
            if l < r3:
                preset_icon_image[i - (r - r3), j - (r - r3)] = p_image[i, j]
    return reset_icon_image


def addition_icon_autograph(source_image_path: str,
                            output_path: str,
                            icon_path=None,
                            autograph=None,
                            icon_method="right_down_circle",
                            autograph_method="right_down",
                            border=30,
                            icon_size=260
                            ):
    """
    Add icon and signature text to the image

    :param source_image_path:
    :param output_path:
    :param icon_path:
    :param autograph:
    :param icon_method:
    :param autograph_method:
    :param border:
    :param icon_size:
    :return:

    Functions:
    ---------
        Adds a small circular icon to the (left / right) (top / bottom) corner of the specified image
        Adds the specified text logo to the (left / right) (top / bottom) corner of the specified image

    Application:
    ---------
        制作微信国旗头像

    Example:
    ---------
        >>> addition_icon_autograph(
        ...    source_image_path="imgs/IMG_2229.JPG",
        ...    output_path="source_output.png",
        ...    icon_path="imgs/icon.jpg",
        ...    autograph="@61Duke",
        ...    autograph_method="right_down",
        ...    icon_method="right_down_circle"
        ... )

    """
    if not isinstance(source_image_path, str) or not source_image_path:
        raise ValueError("source_image_path param type must string!")
    if not isinstance(output_path, str) or not output_path:
        raise ValueError("output_path param type must string!")
    if icon_path and not isinstance(icon_path, str):
        raise ValueError("icon_path param type must string!")
    if autograph and not isinstance(autograph, str):
        raise ValueError("autograph param type must string!")
    if not isinstance(icon_method, str) or not icon_path:
        raise ValueError("icon_method param type must string!")
    if not isinstance(autograph_method, str) or not autograph_method:
        raise ValueError("autograph_method param type must string!")
    if not isinstance(border, int):
        raise ValueError("border param type must int!")
    if not isinstance(icon_size, int):
        raise ValueError("icon_size param type must int!")

    print("Reminding: 建议图像的大小在1000*1000像素而且最好是正方形，否则图像会处理变形！")
    source_image = Image.open(source_image_path).convert("RGBA").resize((1080, 1080), Image.ANTIALIAS)
    if icon_path:
        icon_image = Image.open(icon_path).convert("RGBA")
    else:
        icon_image = Image.new('RGBA', (0, 0))

    # Source Image Processing
    source_image_size = min(source_image.size)
    reset_source_image = Image.new(
        'RGBA',
        (source_image_size + border * 2, source_image_size + border * 2),
        (255, 255, 255)
    )
    reset_source_image.paste(source_image, (border, border))

    # icon Image Processing
    if icon_method == "right_down_circle" and icon_image.size != (0, 0):
        icon_image = icon_image.resize((icon_size, icon_size), Image.ANTIALIAS)
        reset_icon_image = Image.new('RGBA', (icon_size, icon_size), (255, 255, 255, 0))
        reset_icon_image = _circle(icon_image, reset_icon_image, icon_size)
        r, g, b, a = reset_icon_image.split()
        locate = source_image_size + border // 2 - icon_size
        reset_source_image.paste(reset_icon_image, (locate, locate), mask=a)

    elif icon_method == "left_down_circle" and icon_image.size != (0, 0):
        icon_image = icon_image.resize((icon_size, icon_size), Image.ANTIALIAS)
        reset_icon_image = Image.new('RGBA', (icon_size, icon_size), (255, 255, 255, 0))
        reset_icon_image = _circle(icon_image, reset_icon_image, icon_size)
        r, g, b, a = reset_icon_image.split()
        locate = source_image_size + border // 2 - icon_size
        reset_source_image.paste(reset_icon_image, (3 * border // 2, locate), mask=a)

    elif icon_method == "right_up_circle" and icon_image.size != (0, 0):
        icon_image = icon_image.resize((icon_size, icon_size), Image.ANTIALIAS)
        reset_icon_image = Image.new('RGBA', (icon_size, icon_size), (255, 255, 255, 0))
        reset_icon_image = _circle(icon_image, reset_icon_image, icon_size)
        r, g, b, a = reset_icon_image.split()
        locate = source_image_size + border // 2 - icon_size
        reset_source_image.paste(reset_icon_image, (locate, border // 2 * 3), mask=a)
    elif icon_method == "left_up_circle" and icon_image.size != (0, 0):
        icon_image = icon_image.resize((icon_size, icon_size), Image.ANTIALIAS)
        reset_icon_image = Image.new('RGBA', (icon_size, icon_size), (255, 255, 255, 0))
        reset_icon_image = _circle(icon_image, reset_icon_image, icon_size)
        r, g, b, a = reset_icon_image.split()
        reset_source_image.paste(reset_icon_image, (3 * border // 2, border // 2 * 3), mask=a)
    else:
        raise ValueError(f"This icon_method({icon_method}) not Support!")

    size = reset_source_image.size
    length = len(autograph) * 3
    draw = ImageDraw.Draw(reset_source_image)

    # 华文细黑.ttf字体下载url为：http://www.onlinedown.net/soft/580653.htm
    # font = ImageFont.truetype("/System/Library/Fonts/Menlo.ttc", 20)
    if autograph_method == "right_down" and autograph:
        width, height = size[0] - 150, size[1] - 25
    elif autograph_method == "left_down" and autograph:
        width, height = 150, size[1] - 25
    elif autograph_method == "right_up" and autograph:
        width, height = size[0] - 150, 10
    elif autograph_method == "left_up" and autograph:
        width, height = 150, 10
    else:
        raise ValueError(f"This autograph_method({autograph_method}) not Support!")

    draw.text((width - length, height), autograph.encode("utf-8"), fill='black')
    if ".jpg" in output_path:
        return reset_source_image.convert("RGB").save(output_path)
    return reset_source_image.save(output_path)


if __name__ == '__main__':
    pass
